// 定义字符串类型
let str1: string = "hello";

let str2: string;
str2 = "hi";

// 会有自动类型推断
// let str3 = "bye";
// str3 = 5;

// 定义数字类型
let num1: number = 3;
num1 = 4;

// 定义布尔值
let show: boolean = true;
show = false;

// 定义undefined
let udf: undefined = undefined;

// 定义null
let nl: null = null;

// 联合类型
let a: number | boolean | string = 3;
a = true;
a = "3";

// 任意类型 any
let b: any = [1, 2, 3];

// 数组类型
let arr1: number[] = [1, 2, 3, 4, 5];
let arr2: Array<number> = [1, 2, 3, 4, 5]; // 泛型
let arr3: (number | boolean)[] = [1, 2, true];
let arr4: Array<number | boolean> = [1, 2, true];

// 要求数组只能是两项，并且第一项只能是数字，第二项只能是字符串
// 元组类型, 数组类型的扩展
let arr5: [number, string] = [2, "abc"];
// arr5 = arr5.concat(3)

// 对象类型
// 接口
interface ObjType {
  name: string;
  age: number;
  likes: string[];
  // 问号表示可选属性
  sex?: number;
  // 索引签名
  [propname: string]: any;
}

let obj1: ObjType = {
  name: "zhangsan",
  age: 20,
  likes: ["唱歌", "跳舞"],
  a: 3,
  b: 5,
  x: {
    sd: "ggg",
  },
};
obj1.sex = 1;

interface ItemType {
  name: string;
  id: number;
}
let list: ItemType[] = [
  {
    name: "zhangsan",
    id: 1,
  },
  {
    name: "lisi",
    id: 2,
  },
];

interface Obj2Type {
  name: string;
  age: number;
  children?: Obj2Type[];
}
let obj2: Obj2Type = {
  name: "zhangsan",
  age: 50,
  children: [
    {
      name: "zhangsi",
      age: 30,
    },
    {
      name: "zhangwu",
      age: 25,
    },
  ],
};

// 枚举类型
enum Color {
  Red = 5,
  Green = 10,
  Blue = 15,
}
let g: Color = Color.Green;
// console.log(g);
let abc = Color[15];
// console.log(abc);

// 函数类型
// 函数不写类型，写的是函数的返回值的类型
function fn(): number {
  return 10;
}

// void类型，表示函数没有返回值
function fn1(): void {
  console.log(123);
}

// 函数参数是必须要加类型的
function fn2(x: string, y: number): string {
  return x + y;
}
fn2("3", 5);

// fn3的类型一般不写，由ts进行类型推断
const fn3: (x: number, y: number) => number = (
  x: number,
  y: number
): number => {
  return x + y;
};
fn3(4, 5);

// never类型，从不
function fn4(): never {
  while (true) {}
}

let a1 = 3;
function fn5(): number | never {
  if (a1 > 1) {
    return 1;
  } else {
    throw new Error("错误");
  }
}

// 函数参数的可选
function fn6(x: number, y?: number): number {
  return y ? x + y : x;
}
fn6(3);

// 泛型
function fn7<T>(x: T, y: T) {
  return 3;
}
fn7<number>(3, 4);
fn7<string>("3", "4");

// 类
class Animal {
  constructor(str: string) {
    this.name1 = str;
  }
  name1: string = "dog";
  sayName(): string {
    return this.name1;
  }
}

// 类的继承
class Dog extends Animal {
  constructor(str: string) {
    // super用来调用父类的constructor
    super(str);
  }
}

// 类的实例化
// 实例化的时候，就会自动调用构造函数的constructor构造器
const dog = new Dog("cat");

console.log(dog.name1);
